package ca.camosun.bouncer.components;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

public class SensorWrapper implements SensorEventListener {
	private static final float JITTER = 0.2F;
	private static final float GRAVITY = 9.8F;
	private static final int TICK_INTERVAL = 1;

	private SensorManager mSensorManager;
	private Sensor mSensor;
	private Tickable onSensorChangeCallback;

	private float oldx;
	private float oldy;
	private float oldz;

	private int sampleCount = 0;

	public SensorWrapper(SensorManager inSensorManager,
			Tickable inOnSensorChangeCallback) {
		mSensorManager = inSensorManager;
		mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
		onSensorChangeCallback = inOnSensorChangeCallback;
	}

	public void stopListening() {
		mSensorManager.unregisterListener(this, mSensor);
	}

	public void startListening() {
		mSensorManager.registerListener(this, mSensor,
				SensorManager.SENSOR_DELAY_FASTEST);
	}

	@Override
	public void onSensorChanged(SensorEvent accel) {
		float newX = -accel.values[0];
		float newY = -accel.values[1];
		float newZ = accel.values[2];

		newX = unsquare(newX);
		newY = unsquare(newY);
		newZ = newZ - GRAVITY;

		if (sampleCount == 0) {
			sampleCount++;

			oldx = newX;
			oldy = newY;
			oldz = newZ;

			return;
		}

		sampleCount++;

		if (!isJitter(oldx, newX)) {
			oldx = newX;
		}
		if (!isJitter(oldy, newY)) {
			oldy = newY;
		}
		if (!isJitter(oldz, newZ)) {
			oldz = newZ;
		}

		if (sampleCount % TICK_INTERVAL == 0) {
			onSensorChangeCallback.tick(Math.round(newX), Math.round(newY),
					Math.round(newZ));
		}
	}

	@Override
	public void onAccuracyChanged(Sensor arg0, int arg1) {
		// TODO Auto-generated method stub
	}

	private boolean isJitter(float oldValue, float newValue) {
		float delta = newValue - oldValue;

		if (delta < JITTER) {
			return true;
		}

		return false;
	}

	private float unsquare(double number) {
		int sign = 1;

		if (number < 0) {
			sign = -1;
			number = Math.abs(number);
		}

		float sqrt = (float) Math.sqrt(number);

		return sign * sqrt;
	}

}